//
// Created by 17775 on 2024/9/26.
//

#include "LiveMode_CrossSection.h"

LiveMode_CrossSection::LiveMode_CrossSection(int &docId) : _nDocIdLive(docId), crossSectionDataReceiveQueueObserver(new CrossSectionDataReceiveQueueObserver()) {

}

void LiveMode_CrossSection::getCrossData() {
    m_crossSectionThread = std::thread(&LiveMode_CrossSection::getCrossSectionData, this);
}

void LiveMode_CrossSection::getCrossSectionData() {
    try {
        while(_isGettingNewCrossSectionData.load(std::memory_order_acquire)) {
            RayCi_LiveMode_CrossSection_isValid(_nDocIdLive, 0, &_bCrossSectionValid);
            if(_bCrossSectionValid) {
                RayCi_LiveMode_CrossSection_getDataLength(_nDocIdLive, 0, &iDataLength);
                if(iDataLength != 0) {
                    std::vector<float> dXPositions_buffer;
                    std::vector<float> dYPositions_buffer;
                    std::vector<float> dIntensity_buffer;
                    std::vector<float> dFitFunction_buffer;
                    dXPositions_buffer.resize(iDataLength);
                    dYPositions_buffer.resize(iDataLength);
                    dIntensity_buffer.resize(iDataLength);
                    dFitFunction_buffer.resize(iDataLength);
                    RayCi_LiveMode_CrossSection_getDataAsBinary(_nDocIdLive, 0, dXPositions_buffer.data(), &iDataLength, dYPositions_buffer.data(),
                                                                &iDataLength, dIntensity_buffer.data(), &iDataLength, dFitFunction_buffer.data(), &iDataLength); // occur error
                    std::shared_ptr<PowerProfileData<std::vector<float>>> crossData;
                    _isGettingYCrossSectionData.load(std::memory_order_acquire) ? crossData = std::make_shared<PowerProfileData<std::vector<float>>>(dYPositions_buffer, dIntensity_buffer)
                                                                                : crossData = std::make_shared<PowerProfileData<std::vector<float>>>(dXPositions_buffer, dIntensity_buffer);
                    crossSectionDataReceiveQueueObserver->put(std::move(crossData));
                    if(preDataLength != iDataLength) {
                        preDataLength = iDataLength;
                        emit rescaleCurve();
                    }
                }
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    catch(...) {
        qDebug() << "ERROR";
    }
}

void LiveMode_CrossSection::setAdjustmentActive(bool bActive) const {
    RayCi_LiveMode_CrossSection_Adjustment_setActive(_nDocIdLive, _nIdCS, bActive);
}

void LiveMode_CrossSection::setLimitEnable(bool bEnable) {
    RayCi_LiveMode_CrossSection_Limits_isAvailable(_nDocIdLive, _nIdCS, &_bLimitEnable);
    if(_bLimitEnable) {
        RayCi_LiveMode_CrossSection_Limits_setEnabled(_nDocIdLive, _nIdCS, bEnable);
    }
}

void LiveMode_CrossSection::setAdjustmentMethod(int nMethods) const {
    RayCi_LiveMode_CrossSection_Adjustment_setMethod(_nDocIdLive, _nIdCS, nMethods);
}

void LiveMode_CrossSection::setX_px(int nY) const {
    RayCi_LiveMode_CrossSection_Settings_setX_px(_nDocIdLive, _nIdCS, nY);
}

void LiveMode_CrossSection::setY_px(int nX) const {
    RayCi_LiveMode_CrossSection_Settings_setY_px(_nDocIdLive, _nIdCS, nX);
}

void LiveMode_CrossSection::setRadial_px(double dX, double dY, double dAngle) const {
    RayCi_LiveMode_CrossSection_Settings_setRadial_px(_nDocIdLive, _nIdCS, dX, dY, dAngle);
}

void LiveMode_CrossSection::setArbitrary_px(double dX1, double dY1, double dX2, double dY2) const {
    RayCi_LiveMode_CrossSection_Settings_setArbitrary_px(_nDocIdLive, _nIdCS, dX1, dY1, dX2, dY2);
}

void LiveMode_CrossSection::setCircle_px(double dX, double dY, double dR) const {
    RayCi_LiveMode_CrossSection_Settings_setCircle_px(_nDocIdLive, _nIdCS, dX, dY, dR);
}

void LiveMode_CrossSection::stopCrossSectionThread() {
    _isGettingNewCrossSectionData.store(false, std::memory_order_release);
    if (m_crossSectionThread.joinable()) {
        m_crossSectionThread.join();
    }
}

void LiveMode_CrossSection::closeCrossSectionWindow() const {
    RayCi_LiveMode_CrossSection_Window_close(_nDocIdLive, _nIdCS);
}

void LiveMode_CrossSection::addPowerProfileDataListener(CrossSectionDataReceiveListener *listener) const {
    crossSectionDataReceiveQueueObserver->addListener(listener);
}

LiveMode_CrossSection::~LiveMode_CrossSection() {
    _isGettingNewCrossSectionData.store(false, std::memory_order_release);
    if (m_crossSectionThread.joinable()) {
        m_crossSectionThread.join();
    }
    crossSectionDataReceiveQueueObserver->interrupt();
    crossSectionDataReceiveQueueObserver = nullptr;
}